

#ifndef __COMM_MSG_DCU_INFO_H__
#define __COMM_MSG_DCU_INFO_H__

#include "comm/comm_topic_name.h"
#include "comm/comm_base.h"
#include <comm_msg/dcu_info.h>
#include <ros/ros.h>
#include <iostream>
#include <list>
#include <vector>

using namespace std;

typedef struct {
    UINT08 batQuantity;             /* 电量，百分比的值 */
    INT08  batTemp;
    float  batVol;
    
    bool   isAutoMode;
    bool   isRemoteControl;
    bool   isStopByEdgeContact;
    bool   isStopByEmergeSw;

    bool   isRaining;
    bool   isWaterEnough;
    bool   isRubbishFull;
    
    bool   isUltraFault;
    
    bool   isMoveMotorFault;
    bool   isTurnMotorFault;
    bool   isBrakeSysFault;
    
    bool   isCleanBrushFault;
    bool   isCleanFanFault;
    bool   isCleanShakeFault;    
} DCU_INFO_STRU;

typedef struct {
    char   turnAngle;                   /* 小车当前转弯角，单位度 */
    bool   isDspFault;                  /* 判断通信是否正常，如果不正常则认为故障 */
} DCU_STATE_STRU;

typedef struct {
    DCU_INFO_STRU  stDcuInfo;
    DCU_STATE_STRU stDcuState;
} DCU_INFO_EX_STRU;

/**************************************************************************************
功能描述: 发布消息
修改记录:
**************************************************************************************/
class DCU_INFO_SENDER_C
{
public:
    DCU_INFO_SENDER_C(ros::NodeHandle &nh)
    {
        publisher_ = nh.advertise<comm_msg::dcu_info>(TOPIC_NAME_DCU_INFO, 1);

        InitMsg();
    }

    void Send(const DCU_INFO_STRU &stDcuInfo, float moveCtrlTurnAngle, bool isDspFault)
    {
        stMsg_.batteryPowerLeftRate     = stDcuInfo.batQuantity;
        stMsg_.batteryTemperature       = stDcuInfo.batTemp;
        stMsg_.batteryVoltage           = stDcuInfo.batVol;

        stMsg_.isAutoMode               = stDcuInfo.isAutoMode;
        stMsg_.isRemoteControl          = stDcuInfo.isRemoteControl;
        stMsg_.isStopByEdgeContact      = stDcuInfo.isStopByEdgeContact;
        stMsg_.isStopByEmergeSw         = stDcuInfo.isStopByEmergeSw;
        stMsg_.moveCtrlTurnAngle        = (char)RADIAN_TO_ANGLE(moveCtrlTurnAngle);

        stMsg_.isRaining                = stDcuInfo.isRaining;
        stMsg_.isWaterEnough            = stDcuInfo.isWaterEnough;
        stMsg_.isRubbishFull            = stDcuInfo.isRubbishFull;

        stMsg_.isDspFault               = isDspFault;
        stMsg_.isUltraFault             = stDcuInfo.isUltraFault;
        stMsg_.isMoveMotorFault         = stDcuInfo.isMoveMotorFault;
        stMsg_.isTurnMotorFault         = stDcuInfo.isTurnMotorFault;
        stMsg_.isBrakeSysFault          = stDcuInfo.isBrakeSysFault;
        stMsg_.isBrushSysFault          = stDcuInfo.isCleanBrushFault;
        stMsg_.isFanSysFault            = stDcuInfo.isCleanFanFault;
        stMsg_.isShakeSysFault          = stDcuInfo.isCleanShakeFault;

        publisher_.publish(stMsg_);
    }
    
private:
    ros::Publisher     publisher_;
    comm_msg::dcu_info stMsg_;

    void InitMsg(void)
    {
        stMsg_.batteryPowerLeftRate = 0;
        stMsg_.batteryTemperature   = 0;
        stMsg_.batteryVoltage       = 0;

        stMsg_.isAutoMode           = false;
        stMsg_.isRemoteControl      = false;
        stMsg_.isStopByEmergeSw     = false;
        stMsg_.isStopByEdgeContact  = false;
        stMsg_.moveCtrlTurnAngle    = 0;
        
        stMsg_.isRaining            = false;
        stMsg_.isWaterEnough        = false;
        stMsg_.isRubbishFull        = false;
        
        stMsg_.isDspFault           = false;
        stMsg_.isUltraFault         = false;
        stMsg_.isMoveMotorFault     = false;
    }
};

/**************************************************************************************
功能描述: 接收消息
修改记录:
**************************************************************************************/
class DCU_INFO_RECEIVER_C
{
public:
    DCU_INFO_RECEIVER_C(ros::NodeHandle &nh, double overTime = 2.5)
    {
        objInvalidTimer_.SetOverTime(overTime);
        receiver_ = nh.subscribe(TOPIC_NAME_DCU_INFO, 1, &DCU_INFO_RECEIVER_C::ReceiveMsgCallBack, this);
    }

    const DCU_INFO_EX_STRU *Get(void)
    {
        if (objInvalidTimer_.IsTimeOut()) {
            return NULL;
        }

        return &stDcuInfo;
    }
    
private:
    ros::Subscriber  receiver_;
    
    TIMER_C          objInvalidTimer_;       /* 数据失效定时器，超时后数据无效 */
    DCU_INFO_EX_STRU stDcuInfo;

    void ReceiveMsgCallBack(const comm_msg::dcu_info::ConstPtr &pstMsg)
    {
        objInvalidTimer_.Reset();
        
        stDcuInfo.stDcuInfo.batQuantity                = pstMsg->batteryPowerLeftRate;
        stDcuInfo.stDcuInfo.batTemp                    = pstMsg->batteryTemperature;
        stDcuInfo.stDcuInfo.batVol                     = pstMsg->batteryVoltage;

        stDcuInfo.stDcuInfo.isAutoMode                 = pstMsg->isAutoMode;
        stDcuInfo.stDcuInfo.isRemoteControl            = pstMsg->isRemoteControl;
        stDcuInfo.stDcuInfo.isStopByEdgeContact        = pstMsg->isStopByEdgeContact;
        stDcuInfo.stDcuInfo.isStopByEmergeSw           = pstMsg->isStopByEmergeSw;

        stDcuInfo.stDcuInfo.isRaining                  = pstMsg->isRaining;
        stDcuInfo.stDcuInfo.isWaterEnough              = pstMsg->isWaterEnough;        
        stDcuInfo.stDcuInfo.isRubbishFull              = pstMsg->isRubbishFull;
        
        stDcuInfo.stDcuInfo.isUltraFault               = pstMsg->isUltraFault;
        stDcuInfo.stDcuInfo.isMoveMotorFault           = pstMsg->isMoveMotorFault;
        stDcuInfo.stDcuInfo.isTurnMotorFault           = pstMsg->isTurnMotorFault;
        stDcuInfo.stDcuInfo.isBrakeSysFault            = pstMsg->isBrakeSysFault;
        stDcuInfo.stDcuInfo.isCleanBrushFault          = pstMsg->isBrushSysFault;
        stDcuInfo.stDcuInfo.isCleanFanFault            = pstMsg->isFanSysFault;
        stDcuInfo.stDcuInfo.isCleanShakeFault          = pstMsg->isShakeSysFault;
        
        stDcuInfo.stDcuState.turnAngle                 = pstMsg->moveCtrlTurnAngle;
        stDcuInfo.stDcuState.isDspFault                = pstMsg->isDspFault;
    }
};


#endif

